// variant.cpp
#include "ly/variant.hpp"
#include <limits>
#include <sstream>
#include <stdexcept>

namespace ly {

// Getter 方法实现
bool Variant::to_bool() const {
  switch (m_type) {
    case type::t_nil:
      return false;
    case type::t_bool:
      return m_var.m_bool;
    case type::t_char:
      return m_var.m_char != 0;
    case type::t_uint8:
      return m_var.m_uint8 != 0;
    case type::t_int8:
      return m_var.m_int8 != 0;
    case type::t_uint16:
      return m_var.m_uint16 != 0;
    case type::t_int16:
      return m_var.m_int16 != 0;
    case type::t_uint32:
      return m_var.m_uint32 != 0;
    case type::t_int32:
      return m_var.m_int32 != 0;
    case type::t_uint64:
      return m_var.m_uint64 != 0;
    case type::t_int64:
      return m_var.m_int64 != 0;
    case type::t_float:
      return m_var.m_float != 0.0f;
    case type::t_double:
      return m_var.m_double != 0.0;
    case type::t_string:
      return !m_string.empty();
  }
  return false;
}

std::string Variant::to_string() const {
  switch (m_type) {
    case type::t_nil:
      return "nil";
    case type::t_bool:
      return m_var.m_bool ? "true" : "false";
    case type::t_char:
      return std::string(1, m_var.m_char);
    case type::t_uint8:
      return std::to_string(m_var.m_uint8);
    case type::t_int8:
      return std::to_string(m_var.m_int8);
    case type::t_uint16:
      return std::to_string(m_var.m_uint16);
    case type::t_int16:
      return std::to_string(m_var.m_int16);
    case type::t_uint32:
      return std::to_string(m_var.m_uint32);
    case type::t_int32:
      return std::to_string(m_var.m_int32);
    case type::t_uint64:
      return std::to_string(m_var.m_uint64);
    case type::t_int64:
      return std::to_string(m_var.m_int64);
    case type::t_float:
      return std::to_string(m_var.m_float);
    case type::t_double:
      return std::to_string(m_var.m_double);
    case type::t_string:
      return m_string;
  }
  return "";
}

double Variant::to_double() const {
  switch (m_type) {
    case type::t_nil:
      return 0.0;
    case type::t_bool:
      return static_cast<double>(m_var.m_bool);
    case type::t_char:
      return static_cast<double>(m_var.m_char);
    case type::t_uint8:
      return static_cast<double>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<double>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<double>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<double>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<double>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<double>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<double>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<double>(m_var.m_int64);
    case type::t_float:
      return static_cast<double>(m_var.m_float);
    case type::t_double:
      return m_var.m_double;
    case type::t_string:
      return std::stod(m_string);
  }
  return 0.0;
}

float Variant::to_float() const {
  switch (m_type) {
    case type::t_nil:
      return 0.0f;
    case type::t_bool:
      return static_cast<float>(m_var.m_bool);
    case type::t_char:
      return static_cast<float>(m_var.m_char);
    case type::t_uint8:
      return static_cast<float>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<float>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<float>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<float>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<float>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<float>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<float>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<float>(m_var.m_int64);
    case type::t_float:
      return m_var.m_float;
    case type::t_double:
      return static_cast<float>(m_var.m_double);
    case type::t_string:
      return std::stof(m_string);
  }
  return 0.0f;
}

// 各种整数类型的转换实现
uint8_t Variant::to_uint8() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<uint8_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<uint8_t>(m_var.m_char);
    case type::t_uint8:
      return m_var.m_uint8;
    case type::t_int8:
      return static_cast<uint8_t>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<uint8_t>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<uint8_t>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<uint8_t>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<uint8_t>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<uint8_t>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<uint8_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<uint8_t>(m_var.m_float);
    case type::t_double:
      return static_cast<uint8_t>(m_var.m_double);
    case type::t_string:
      return static_cast<uint8_t>(std::stoi(m_string));
  }
  return 0;
}

int8_t Variant::to_int8() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<int8_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<int8_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<int8_t>(m_var.m_uint8);
    case type::t_int8:
      return m_var.m_int8;
    case type::t_uint16:
      return static_cast<int8_t>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<int8_t>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<int8_t>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<int8_t>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<int8_t>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<int8_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<int8_t>(m_var.m_float);
    case type::t_double:
      return static_cast<int8_t>(m_var.m_double);
    case type::t_string:
      return static_cast<int8_t>(std::stoi(m_string));
  }
  return 0;
}

uint16_t Variant::to_uint16() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<uint16_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<uint16_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<uint16_t>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<uint16_t>(m_var.m_int8);
    case type::t_uint16:
      return m_var.m_uint16;
    case type::t_int16:
      return static_cast<uint16_t>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<uint16_t>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<uint16_t>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<uint16_t>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<uint16_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<uint16_t>(m_var.m_float);
    case type::t_double:
      return static_cast<uint16_t>(m_var.m_double);
    case type::t_string:
      return static_cast<uint16_t>(std::stoi(m_string));
  }
  return 0;
}

int16_t Variant::to_int16() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<int16_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<int16_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<int16_t>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<int16_t>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<int16_t>(m_var.m_uint16);
    case type::t_int16:
      return m_var.m_int16;
    case type::t_uint32:
      return static_cast<int16_t>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<int16_t>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<int16_t>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<int16_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<int16_t>(m_var.m_float);
    case type::t_double:
      return static_cast<int16_t>(m_var.m_double);
    case type::t_string:
      return static_cast<int16_t>(std::stoi(m_string));
  }
  return 0;
}

uint32_t Variant::to_uint32() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<uint32_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<uint32_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<uint32_t>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<uint32_t>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<uint32_t>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<uint32_t>(m_var.m_int16);
    case type::t_uint32:
      return m_var.m_uint32;
    case type::t_int32:
      return static_cast<uint32_t>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<uint32_t>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<uint32_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<uint32_t>(m_var.m_float);
    case type::t_double:
      return static_cast<uint32_t>(m_var.m_double);
    case type::t_string:
      return static_cast<uint32_t>(std::stol(m_string));
  }
  return 0;
}

int32_t Variant::to_int32() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<int32_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<int32_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<int32_t>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<int32_t>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<int32_t>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<int32_t>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<int32_t>(m_var.m_uint32);
    case type::t_int32:
      return m_var.m_int32;
    case type::t_uint64:
      return static_cast<int32_t>(m_var.m_uint64);
    case type::t_int64:
      return static_cast<int32_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<int32_t>(m_var.m_float);
    case type::t_double:
      return static_cast<int32_t>(m_var.m_double);
    case type::t_string:
      return std::stol(m_string);
  }
  return 0;
}

uint64_t Variant::to_uint64() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<uint64_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<uint64_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<uint64_t>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<uint64_t>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<uint64_t>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<uint64_t>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<uint64_t>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<uint64_t>(m_var.m_int32);
    case type::t_uint64:
      return m_var.m_uint64;
    case type::t_int64:
      return static_cast<uint64_t>(m_var.m_int64);
    case type::t_float:
      return static_cast<uint64_t>(m_var.m_float);
    case type::t_double:
      return static_cast<uint64_t>(m_var.m_double);
    case type::t_string:
      return std::stoull(m_string);
  }
  return 0;
}

int64_t Variant::to_int64() const {
  switch (m_type) {
    case type::t_nil:
      return 0;
    case type::t_bool:
      return static_cast<int64_t>(m_var.m_bool);
    case type::t_char:
      return static_cast<int64_t>(m_var.m_char);
    case type::t_uint8:
      return static_cast<int64_t>(m_var.m_uint8);
    case type::t_int8:
      return static_cast<int64_t>(m_var.m_int8);
    case type::t_uint16:
      return static_cast<int64_t>(m_var.m_uint16);
    case type::t_int16:
      return static_cast<int64_t>(m_var.m_int16);
    case type::t_uint32:
      return static_cast<int64_t>(m_var.m_uint32);
    case type::t_int32:
      return static_cast<int64_t>(m_var.m_int32);
    case type::t_uint64:
      return static_cast<int64_t>(m_var.m_uint64);
    case type::t_int64:
      return m_var.m_int64;
    case type::t_float:
      return static_cast<int64_t>(m_var.m_float);
    case type::t_double:
      return static_cast<int64_t>(m_var.m_double);
    case type::t_string:
      return std::stoll(m_string);
  }
  return 0;
}

// 赋值操作符实现
Variant& Variant::operator=(bool v) {
  m_type = type::t_bool;
  m_var.m_bool = v;
  return *this;
}

Variant& Variant::operator=(char v) {
  m_type = type::t_char;
  m_var.m_char = v;
  return *this;
}

Variant& Variant::operator=(uint8_t v) {
  m_type = type::t_uint8;
  m_var.m_uint8 = v;
  return *this;
}

Variant& Variant::operator=(int8_t v) {
  m_type = type::t_int8;
  m_var.m_int8 = v;
  return *this;
}

Variant& Variant::operator=(uint16_t v) {
  m_type = type::t_uint16;
  m_var.m_uint16 = v;
  return *this;
}

Variant& Variant::operator=(int16_t v) {
  m_type = type::t_int16;
  m_var.m_int16 = v;
  return *this;
}

Variant& Variant::operator=(uint32_t v) {
  m_type = type::t_uint32;
  m_var.m_uint32 = v;
  return *this;
}

Variant& Variant::operator=(int32_t v) {
  m_type = type::t_int32;
  m_var.m_int32 = v;
  return *this;
}

Variant& Variant::operator=(uint64_t v) {
  m_type = type::t_uint64;
  m_var.m_uint64 = v;
  return *this;
}

Variant& Variant::operator=(int64_t v) {
  m_type = type::t_int64;
  m_var.m_int64 = v;
  return *this;
}

Variant& Variant::operator=(float v) {
  m_type = type::t_float;
  m_var.m_float = v;
  return *this;
}

Variant& Variant::operator=(double v) {
  m_type = type::t_double;
  m_var.m_double = v;
  return *this;
}

Variant& Variant::operator=(const std::string& s) {
  m_type = type::t_string;
  m_string = s;
  return *this;
}

Variant& Variant::operator=(const char* s) {
  m_type = type::t_string;
  m_string = s;
  return *this;
}

// 比较操作符实现
bool Variant::operator==(const Variant& v) const {
  if (m_type != v.m_type) {
    return false;
  }

  switch (m_type) {
    case type::t_nil:
      return true;
    case type::t_bool:
      return m_var.m_bool == v.m_var.m_bool;
    case type::t_char:
      return m_var.m_char == v.m_var.m_char;
    case type::t_uint8:
      return m_var.m_uint8 == v.m_var.m_uint8;
    case type::t_int8:
      return m_var.m_int8 == v.m_var.m_int8;
    case type::t_uint16:
      return m_var.m_uint16 == v.m_var.m_uint16;
    case type::t_int16:
      return m_var.m_int16 == v.m_var.m_int16;
    case type::t_uint32:
      return m_var.m_uint32 == v.m_var.m_uint32;
    case type::t_int32:
      return m_var.m_int32 == v.m_var.m_int32;
    case type::t_uint64:
      return m_var.m_uint64 == v.m_var.m_uint64;
    case type::t_int64:
      return m_var.m_int64 == v.m_var.m_int64;
    case type::t_float:
      return m_var.m_float == v.m_var.m_float;
    case type::t_double:
      return m_var.m_double == v.m_var.m_double;
    case type::t_string:
      return m_string == v.m_string;
  }
  return false;
}

bool Variant::operator!=(const Variant& v) const {
  return !(*this == v);
}

bool Variant::operator<(const Variant& v) const {
  // 首先比较类型
  if (m_type != v.m_type) {
    return m_type < v.m_type;
  }

  // 类型相同的情况下，按值排序
  switch (m_type) {
    case type::t_nil:
      return false;
    case type::t_bool:
      return m_var.m_bool < v.m_var.m_bool;
    case type::t_char:
      return m_var.m_char < v.m_var.m_char;
    case type::t_uint8:
      return m_var.m_uint8 < v.m_var.m_uint8;
    case type::t_int8:
      return m_var.m_int8 < v.m_var.m_int8;
    case type::t_uint16:
      return m_var.m_uint16 < v.m_var.m_uint16;
    case type::t_int16:
      return m_var.m_int16 < v.m_var.m_int16;
    case type::t_uint32:
      return m_var.m_uint32 < v.m_var.m_uint32;
    case type::t_int32:
      return m_var.m_int32 < v.m_var.m_int32;
    case type::t_uint64:
      return m_var.m_uint64 < v.m_var.m_uint64;
    case type::t_int64:
      return m_var.m_int64 < v.m_var.m_int64;
    case type::t_float:
      return m_var.m_float < v.m_var.m_float;
    case type::t_double:
      return m_var.m_double < v.m_var.m_double;
    case type::t_string:
      return m_string < v.m_string;
  }
  return false;
}

bool Variant::operator>(const Variant& v) const {
  return v < *this;
}

bool Variant::operator<=(const Variant& v) const {
  return !(v < *this);
}

bool Variant::operator>=(const Variant& v) const {
  return !(*this < v);
}

// 算术操作符实现
Variant Variant::operator+(const Variant& v) const {
  Variant result;

  // 只对数值类型进行加法运算
  if ((m_type >= type::t_uint8 && m_type <= type::t_double) && (v.m_type >= type::t_uint8 && v.m_type <= type::t_double)) {

    // 如果任一操作数是double，则结果为double
    if (m_type == type::t_double || v.m_type == type::t_double) {
      result = to_double() + v.to_double();
    }
    // 如果任一操作数是float，则结果为float
    else if (m_type == type::t_float || v.m_type == type::t_float) {
      result = to_float() + v.to_float();
    }
    // 否则结果为int64_t
    else {
      result = to_int64() + v.to_int64();
    }
  }

  return result;
}

Variant Variant::operator-(const Variant& v) const {
  Variant result;

  // 只对数值类型进行减法运算
  if ((m_type >= type::t_uint8 && m_type <= type::t_double) && (v.m_type >= type::t_uint8 && v.m_type <= type::t_double)) {

    // 如果任一操作数是double，则结果为double
    if (m_type == type::t_double || v.m_type == type::t_double) {
      result = to_double() - v.to_double();
    }
    // 如果任一操作数是float，则结果为float
    else if (m_type == type::t_float || v.m_type == type::t_float) {
      result = to_float() - v.to_float();
    }
    // 否则结果为int64_t
    else {
      result = to_int64() - v.to_int64();
    }
  }

  return result;
}

Variant Variant::operator*(const Variant& v) const {
  Variant result;

  // 只对数值类型进行乘法运算
  if ((m_type >= type::t_uint8 && m_type <= type::t_double) && (v.m_type >= type::t_uint8 && v.m_type <= type::t_double)) {

    // 如果任一操作数是double，则结果为double
    if (m_type == type::t_double || v.m_type == type::t_double) {
      result = to_double() * v.to_double();
    }
    // 如果任一操作数是float，则结果为float
    else if (m_type == type::t_float || v.m_type == type::t_float) {
      result = to_float() * v.to_float();
    }
    // 否则结果为int64_t
    else {
      result = to_int64() * v.to_int64();
    }
  }

  return result;
}

Variant Variant::operator/(const Variant& v) const {
  Variant result;

  // 只对数值类型进行除法运算
  if ((m_type >= type::t_uint8 && m_type <= type::t_double) && (v.m_type >= type::t_uint8 && v.m_type <= type::t_double)) {

    // 检查除零错误
    if (v.to_double() == 0.0) {
      throw std::runtime_error("Division by zero");
    }

    // 如果任一操作数是double，则结果为double
    if (m_type == type::t_double || v.m_type == type::t_double) {
      result = to_double() / v.to_double();
    }
    // 如果任一操作数是float，则结果为float
    else if (m_type == type::t_float || v.m_type == type::t_float) {
      result = to_float() / v.to_float();
    }
    // 否则结果为int64_t
    else {
      result = to_int64() / v.to_int64();
    }
  }

  return result;
}

}  // namespace ly
